﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace ReversiBackend
{
    public class Game
    {
        /*
         * 
         *   p1 = -1
         *   p2 =  1
         * 
         */

        public Board Board { get; private set; }
        private Player[] players { get; set; }
        public bool Running {get; private set;}

        public delegate void CurrentPlayerChangedHandler(int newCurrentPlayer);
        public event CurrentPlayerChangedHandler CurrentPlayerChanged;

        private int currentPlayer = -1;
        public int CurrentPlayer
        {
            get
            {
                return currentPlayer;
            }
            set
            {
                if (value != currentPlayer)
                {
                    currentPlayer = value;
                    if (CurrentPlayerChanged != null)
                    {
                        CurrentPlayerChanged((currentPlayer == 0) ? (-1) : (1));
                    }
                }
            }
        }

        public Game()
        {
            this.Board = new Board();
            Board.GameOver += new GameOverHandler(Board_GameOver);
            this.players = new Player[2];
            Running = false;
        }

        public event GameOverHandler GameOver;

        void Board_GameOver(int winner)
        {
            Running = false;
            if (GameOver != null)
            {
                GameOver(winner);
            }
        }

        public void NewGame(Player p1, Player p2){
            Board.Clear();
            foreach (Player p in players)
            {
                if (p != null)
                {
                    p.Die();
                }
            }
            this.players[0] = p1;
            this.players[1] = p2;
            CurrentPlayer = 0;
            Running = true;
            if (CurrentPlayerChanged != null)
            {
                CurrentPlayerChanged((currentPlayer == 0) ? (-1) : (1));
            }
            players[currentPlayer].YourTurn();
        }

        public void Pass()
        {
            if (Running)
            {
                CurrentPlayer = 1 - CurrentPlayer;
                if (CurrentPlayerChanged != null)
                {
                    CurrentPlayerChanged((currentPlayer == 0) ? (-1) : (1));
                }
                players[currentPlayer].YourTurn();
            }

        }

        public void Turn(Cell m)
        {
            Board[m] = (CurrentPlayer == 0)? -1 : 1;
            if (Running)
            {
                CurrentPlayer = 1 - CurrentPlayer;
                if (CurrentPlayerChanged != null)
                {
                    CurrentPlayerChanged((currentPlayer == 0) ? (-1) : (1));
                }
                players[currentPlayer].YourTurn();
            }
        }

        #region load/save
        public void DumpData(Dictionary<string, object> data, out Player p1, out Player p2)
        {
            Board.DumpData(data);
            data.Add("currentPlayer", currentPlayer);
            p1 = players[0];
            p2 = players[1];
            
        }

        public void LoadData(Dictionary<string, object> data, Player p1, Player p2)
        {
            Board.LoadData(data);
            
            players[0].Die();
            players[1].Die();
            players[0] = p1;
            players[1] = p2;
            currentPlayer = -1;
            CurrentPlayer = (int)data["currentPlayer"];
            players[CurrentPlayer].YourTurn();
            //TODO: event werfen?
        }
        #endregion
    }
}
